#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#define ONE  (1<<0)
#define TWO  (1<<1)
#define FOUR (1<<3)
#define FIVE (1<<4)
#define THREE (1<<2)

//传统C语言对文件的操作
//int main()
//{
//    //访问方式用w是先清空文件内容再从零开始写入，如果没有改文件会自动创建文件
//    //FILE* pf = fopen("log.txt", "w");
//    //a是append也即是追加，其他和w相同
//    //路径如果什么都不写就是相对路径，他会在当前路径下打开文件，当前路径其实就是进程运行时的当前路径(cwd)，可以改变
//    FILE* pf = fopen("log.txt", "a");
//    if(pf == NULL)
//    {
//        perror("open failed\n");
//        return 1;
//    }
//
//    const char* mystr="meimei ai xinshen\n";
//    const char* str = "xinshen shige da shuaige\n";
//
//    //这里strlen(mystr)而不是strlen(mystr)+1 因为只有再C语言中才会以\0结尾，所以不用加1
//    //fwrite(mystr, strlen(mystr), 1, pf);
//    fwrite(mystr, strlen(mystr), 1, pf);
//
//    fclose(pf);
//    return 0;
//}

//其实他就是位操作，可以做到一个整形变量来传递多个信号，用每一个比特位可以传递一个信息
//void show(int flag)
//{
//    //ONE就是最低位为1，其余位为0
//    //这一步操作的意思就是判断flag变量的最低位是否为1，如果为1则执行if
//    if(flag & ONE)
//    {
//        printf("I am exauting task1\n");
//    }
//    if(flag & TWO)
//    {
//        printf("I am exauting task2\n");
//    }
//    if(flag & THREE)
//    {
//        printf("I am exauting task3\n");
//    }
//    if(flag & FOUR)
//    {
//        printf("I am exauting task4\n");
//    }
//}
//
//int main()
//{
//    show(ONE);
//    show(TWO);
//    //两个变量|运算最终变量会把所有变量的1拿到
//    show(THREE | FOUR);
//    show(ONE|TWO|THREE|FOUR|FIVE);
//    return 0;
//}

//系统调用函数open
//int main()
//{
//    umask(0);
//
//    //验证fd=0,1,2是stdin,stdout,stderro
//    //char buff[1024];
//    //ssize_t s = read(0, buff, sizeof(buff));
//    //if(s < 0)
//    //{
//    //    return 1;
//    //}
//    //buff[s] = '\0';
//    //printf("echo : %s\n", buff);
//    //const char* meg = "meimei\n";
//    //const char* mystr = "xinshe shige dashuaige\n";
//    //write(1, meg, strlen(meg));
//    //write(2, mystr, strlen(mystr));
//    
//    close(1);
//    int n = printf("stdin->fd:%d\n", stdin->_fileno);
//    printf("stdout->fd:%d\n", stdout->_fileno);
//    printf("stderror->fd:%d\n", stderr->_fileno);
//    fprintf(stderr, "printf ret :%d\n", n);
//
//    //fopen其实是封装的系统调用open
//    //FILE* pf = fopen("log.txt", "w");
//    //int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);
//    
//    //FILE* pf = fopen("log.txt", "a");
//    //文件描述符其实是文件描述符表的下标，所以他线性增加
//    //int fd1 = open("log1.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);
//    //int fd2 = open("log2.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);
//    //int fd3 = open("log3.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);
//    //int fd4 = open("log4.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);
//    //if(fd1 < 0)
//    //{
//    //    perror("open failed\n");
//    //    return 1;
//    //}
//    //printf("fd1:%d\n", fd1);
//    //printf("fd2:%d\n", fd2);
//    //printf("fd3:%d\n", fd3);
//    //printf("fd4:%d\n", fd4);
//
//    //const char* meg = "meimei ai xinshen\n";
//    //write(fd, meg, strlen(meg));
//
//    //close(fd);
//    return 0;
//}
//

//重定向原理
//int main()
//{
//    umask(0);
//    //close(1);
//    //
//    //int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);
//    //const char* meg = "xinshen ai meimei\n"; 
//    ////fprintf(stderr, "fd:%d\n", fd);
//   ////iwrite(fd, meg, strlen(meg));
//    //write(1, meg, strlen(meg));
//    //
//    //close(fd);
//    
//    //利用dup2系统调用来实现输出重定向 
//    int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);
//    if(fd < 0)
//    {
//        perror("open failed\n");
//        return 1;
//    }
//    
//    //const char* meg = "meimei ai xinshen\n";
//    dup2(fd, 1);
//    close(fd);
//    //使用系统调用接口
//    //write(1, meg, strlen(meg));
//    //使用库函数接口
//    printf("fd:%d\n", fd); //stdout -> 1上层并不知道内核里面的文件描述符内容更改
//    printf("meimei\n");
//    fprintf(stdout, "meimei ai xinshen\n");
//
//
//    //追加重定向
//    //int fd = open("log.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);
//    //if(fd < 0)
//    //{
//    //    perror("open failed\n");
//    //    return 1;
//    //}
//    //
//    //const char* meg = "meimei ai xinshen\n";
//    //dup2(fd, 1);
//    //close(fd);
//    //write(1, meg, strlen(meg));
//    
//    //输入重定向，读选项所以用O_RDONLY
////    int fd = open("log.txt", O_RDONLY);
////    if(fd < 0)
////    {
////        perror("open failed\n");
////    }
////
////    //读到buff数组里面
////    char buff[1024];
////    dup2(fd, 0);
////    close(fd);
////
////    ssize_t s = read(0, buff, sizeof(buff)-1);
////    {
////        buff[s] = '\0';
////        printf("echo# %s",buff);
////    }
//    
//    close(fd);
//    return 0;
//}

//深刻理解文件缓冲区的概念和原理
//int main()
//{
//    //const char* meg = "the files for C language";
//    //const char meg[] = "the files for C language";
//    //printf("hello printf");
//    //fprintf(stdout, "hello fprintf");
//    //fwrite(meg, strlen(meg), 1, stdout);
//    //write(1, meg, sizeof(meg));
//    //close(1);
//    printf("hello meimei");
//    return 0;
//}

int main()
{
    const char* meg = "hello fwrite\n";
    const char* str = "hello wirte\n";

    printf("hello printf\n");
    sleep(2);
    fprintf(stdout, "hello fprintf\n");
    sleep(2);
    fwrite(meg, strlen(meg), 1, stdout);
    sleep(2);

    write(1, str, strlen(str));
    sleep(5);
    //fork();
    return 0;
}
